package com.dingreading.cloud.soms.util;


import com.dingreading.cloud.common.util.*;
import com.dingreading.cloud.soms.dto.*;
import com.dingreading.cloud.soms.entity.*;
import com.dingreading.cloud.soms.service.CaCallNamesService;
import com.dingreading.cloud.soms.service.CmservicesService;
import com.dingreading.cloud.soms.service.StoreProjectCycleService;
import com.dingreading.cloud.soms.service.StoreProjectStageService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 会员订单工具
 */
@Component
public class CmorderUtil {

    @Resource
    private CmservicesService cmservicesService;
    @Resource
    private CaCallNamesService caCallNameService;
    @Resource
    private StoreProjectCycleService cycleService;
    @Resource
    private StoreProjectStageService stageService;


    public static CmorderUtil util;

    @PostConstruct
    public void init() {
        util = this;
    }

    private static final String expType = EnumType.OrderType.EXP.getType();
    private static final String newType = EnumType.OrderType.NEW.getType();
    private static final String renewType = EnumType.OrderType.RENEW.getType();
    private static final String extType = EnumType.OrderType.EXT.getType();
    private static final String emdType = EnumType.OrderType.EMD.getType();
    private static final String giftType = EnumType.OrderType.GIFT.getType();

    private static final int openCardStatus = EnumType.ServiceStatus.OPEN_CARD.getStatus();
    private static final int pauseCardStatus = EnumType.ServiceStatus.PAUSE_CARD.getStatus();
    private static final int consumeStatus = EnumType.ServiceStatus.CONSUME.getStatus();
    private static final String consumeName = EnumType.ServiceStatus.CONSUME.getName();
    private static final int refundStatus = EnumType.ServiceStatus.REFUND.getStatus();
    private static final String refundName = EnumType.ServiceStatus.REFUND.getName();
    private static final int invalidStatus = EnumType.ServiceStatus.INVALID.getStatus();
    private static final int changeStatus = EnumType.ServiceStatus.CHANGE.getStatus();
    private static final String changeName = EnumType.ServiceStatus.CHANGE.getName();

    /**
     * 新建会员服务订单
     */
    public static Cmorders newCmorder(
            Cmorders data, String corpUid, String storeUid, String storeName, String staffUid, String staffName, String memberUid, String memberName,
            String saleStaffUid, String saleStaffFullName, String saleStaffPriPhone, String saleStaffPubPhone, String saleStaffNickName,
            String contractCode, String orderType, Double orderAmount, Date orderDate,
            String giftGotten, String giftRemark, String orderRemark, String payChannelCode, Integer serviceNum, String receiptUid
    ) {
        if (null == data) {
            data = new Cmorders();
            data.setCorpUid(corpUid);
            data.setStoreUid(storeUid);
            data.setStoreName(storeName);
            data.setAddStaffUid(staffUid);
            data.setAddStaffName(staffName);
            data.setOrderCode(KitUtil.getMemberServiceCode());
            data.setMemberUid(memberUid);
            data.setMemberName(memberName);
            data.setStatus(0);
            data.setStatusName("待审批");
            // 正常
            data.setInoutType(1);
            data.setInoutTypeName("收入");
            data.setOrderState(1);
            data.setOrderStateName("正常");
        }
        data.setOrderType(NepUtil.nullToZero(orderType));
        data.setContractCode(NepUtil.nullToZero(contractCode));
        data.setOrderAmount(NepUtil.nullToZero(orderAmount));
        data.setGiftGotten(NepUtil.nullToZero(giftGotten));
        data.setGiftRemark(NepUtil.nullToZero(giftRemark));
        data.setOrderRemark(NepUtil.nullToZero(orderRemark));
        data.setPayChannelCode(NepUtil.nullToZero(payChannelCode));
        data.setOrderDate(orderDate);
        data.setServiceNum(NepUtil.nullToZero(serviceNum));

        data.setSaleStaffUid(NepUtil.nullToZero(saleStaffUid));
        data.setSaleStaffFullName(NepUtil.nullToZero(saleStaffFullName));
        data.setSaleStaffPriPhone(NepUtil.nullToZero(saleStaffPriPhone));
        data.setSaleStaffPubPhone(NepUtil.nullToZero(saleStaffPubPhone));
        data.setSaleStaffNickName(NepUtil.nullToZero(saleStaffNickName));

        data.setLastStaffUid(staffUid);
        data.setLastStaffName(staffName);

        data.setReceiptUid(NepUtil.nullToZero(receiptUid));

        return data;
    }

    /**
     * 会员订单服务详情
     */
    public static Cmservices newService(
            Cmservices service, String orderCode, String orderType, String corpUid, String storeUid, String storeName,
            String memberUid, String memberName, String staffUid, String staffName,
            Long projectId, String projectName, Integer lessonStatus, Integer freeStatus, String productName,
            String productLogsName, Integer productType
    ) {
        service.setUid(KitUtil.getUuid());
        service.setCorpUid(corpUid);
        service.setStoreUid(storeUid);
        service.setStoreName(storeName);
        service.setFromStoreUid(storeUid);
        service.setFromStoreName(storeName);
        service.setOrderCode(orderCode);
        service.setOrderType(orderType);
        service.setMemberUid(memberUid);
        service.setMemberName(memberName);
        service.setStatus(EnumType.ServiceStatus.NO_CARD.getStatus());
        service.setStatusName(EnumType.ServiceStatus.NO_CARD.getName());
        service.setChangeStatus(EnumType.ServiceStatus.NO_CHANGE.getStatus());
        service.setEnding(0);
        service.setEndingType(0);
        service.setEndingTime(null);
        service.setEndingRemark(null);

        if (service.getTotalLessons() != null)
            service.setLeftLessons(service.getTotalLessons());
        if (service.getServiceDays() != null)
            service.setLeftDays(service.getServiceDays());
        service.setAddStaffUid(staffUid);
        service.setAddStaffName(staffName);
        service.setLastStaffUid(staffUid);
        service.setLastStaffName(staffName);

        service.setProductCode(projectId + "");
        service.setProductName(projectName);
        service.setProductType(productType);
        service.setLessonStatus(lessonStatus);
        service.setFreeStatus(freeStatus);
        service.setStoreProductName(productName);
        service.setCycleName(productLogsName);

        return service;
    }


    /**
     * 新建会员服务订单
     */
    public static Cmorders newOrderByProducts(
            String corpUid, String storeUid, String storeName, String memberUid, String memberName,
            Staff staff, String staffUid, String staffName,
            String orderType, String orderDate, String orderRemark
    ) throws Exception {
        Cmorders data = new Cmorders();
        data.setOrderCode(KitUtil.getMemberServiceCode());
        data.setCorpUid(corpUid);
        data.setStoreUid(storeUid);
        data.setStoreName(storeName);
        data.setMemberUid(memberUid);
        data.setMemberName(memberName);
        data.setAddStaffUid(staffUid);
        data.setAddStaffName(staffName);
        data.setStatus(0);
        data.setStatusName("待审批");
        // 正常
        data.setInoutType(1);
        data.setInoutTypeName("收入");
        data.setOrderState(1);
        data.setOrderStateName("正常");
        data.setOrderType(NepUtil.nullToZero(orderType));
        data.setContractCode(null);
        data.setOrderAmount(0d);
        data.setGiftGotten(null);
        data.setGiftRemark(null);
        data.setOrderRemark(orderRemark);
        data.setPayChannelCode(null);
        if (StringUtils.isNotBlank(orderDate))
            data.setOrderDate(DateUtil.parseDate(orderDate));
        else
            data.setOrderDate(null);

        data.setSaleStaffUid(staffUid);
        data.setSaleStaffFullName(staffUid);
        data.setSaleStaffPriPhone(staff.getPriPhone());
        data.setSaleStaffPubPhone(staff.getPubPhone());
        data.setSaleStaffNickName(staff.getNickName());

        data.setLastStaffUid(staffUid);
        data.setLastStaffName(staffName);

        return data;
    }

    /**
     * 根据产品包创建会员订单服务详情
     */
    public static Cmservices newServiceByProductLogs(
            String corpUid, String storeUid, String storeName, String memberUid, String memberName, String staffUid, String staffName,
            String orderCode, String orderType, Integer isGift, String remark,
            StoreProductLogs logs, Map<String, StoreProjects> projectsMap
    ) throws Exception {

        StoreProjects projects = projectsMap.get(logs.getProjectUid());
        if (null == projects)
            throw new DescribeException(500, "产品的服务:" + logs.getProjectName() + "获取失败");

        Cmservices service = new Cmservices();
        service.setUid(KitUtil.getUuid());
        service.setCorpUid(corpUid);
        service.setStoreUid(storeUid);
        service.setStoreName(storeName);
        service.setFromStoreUid(storeUid);
        service.setFromStoreName(storeName);
        service.setOrderCode(orderCode);
        service.setOrderType(orderType);
        service.setMemberUid(memberUid);
        service.setMemberName(memberName);
        service.setStatus(EnumType.ServiceStatus.NO_CARD.getStatus());
        service.setStatusName(EnumType.ServiceStatus.NO_CARD.getName());
        service.setChangeStatus(EnumType.ServiceStatus.NO_CHANGE.getStatus());
        service.setEnding(0);
        service.setEndingType(0);
        service.setEndingTime(null);
        service.setEndingRemark(null);

        service.setAddStaffUid(staffUid);
        service.setAddStaffName(staffName);
        service.setLastStaffUid(staffUid);
        service.setLastStaffName(staffName);
        service.setRemarks(remark);

        String projectUid = logs.getProjectUid();
        String projectName = logs.getProjectName();
        String productUid = logs.getProductUid();
        String productName = logs.getProductName();
        Integer productType = logs.getProductType();
        String productLogUid = logs.getUid();
        String productLogName = logs.getName();
        Integer lessonStatus = logs.getLessonStatus();
        Integer freeStatus = logs.getFreeStatus();
        Integer days = logs.getDays();
        Integer lessons = logs.getLessons();

        // 赠送
        service.setIsGift(isGift);
        // 服务
        service.setProductCode(projects.getId() + "");
        // 服务名称
        service.setProductName(projectName);
        // 服务uid
        service.setProjectUid(projectUid);
        // 排课状态
        service.setLessonStatus(lessonStatus);
        service.setFreeStatus(freeStatus);

        // 产品包uid
        service.setProductUid(productUid);
        // 产品包名称
        service.setStoreProductName(productName);
        // 产品uid
        service.setProductLogUid(productLogUid);
        // 产品名称
        service.setCycleName(productLogName);
        // 产品类型
        service.setProductType(productType);
        // 重复产品包唯一标识
        long timeMillis = System.currentTimeMillis();
        service.setPkgUid(timeMillis + "");

        // 活动天数
        service.setServiceDays(days);
        service.setLeftDays(days);
        // 活动次数
        service.setTotalLessons(lessons);
        service.setLeftLessons(lessons);

        return service;
    }

    /**
     * 创建服务开卡状态的日志
     */
    public static ServiceStatusLogs newStatusLog(
            Cmservices data, String lastStaffUid, String fullName, Integer status,
            Date opDate, Date originDate, Date newDate
    ) {
        ServiceStatusLogs statusLogs = new ServiceStatusLogs();
        statusLogs.setCorpUid(data.getCorpUid());
        statusLogs.setStoreUid(data.getStoreUid());
        statusLogs.setOpStatus(status);
        statusLogs.setServiceUid(data.getUid());
        statusLogs.setOpStaffUid(lastStaffUid);
        statusLogs.setOpStaffFullName(fullName);
        statusLogs.setOriginDate(originDate);
        statusLogs.setNewDate(newDate);
        statusLogs.setOpDate(opDate);
        return statusLogs;
    }

    /**
     * 处理和验证要保存或编辑的服务信息
     */
    public static String dealServiceList(
            List<String> projectUids,
            List<String> productUids,
            List<String> productLogUids,
            List<Cmservices> serviceList,
            String orderType
    ) {
        int containGift = 0;
        for (Cmservices service : serviceList) {
            String projectUid = service.getProjectUid();
            if (StringUtils.isBlank(projectUid))
                return "请选择服务";

            Integer serviceDays = service.getServiceDays();
            if (null == serviceDays || serviceDays <= 0)
                return "请填写正确的活动天数";

            Integer serviceIsGift = service.getIsGift();
            if (orderType.equals(expType)) {
                // 收入类型是赠送时，服务只能选择赠送
                if (!serviceIsGift.equals(0))
                    return "收入类型是体验会员，服务只能选择非赠送";
            }/* else if (projectUid.equals(ScheduleUtil.TIYAN_UID)) {
                return "体验课 的收入类型只能选择：体验会员";
            }*/ else if (orderType.equals(giftType)) {
                // 收入类型是赠送时，服务只能选择赠送
                if (!serviceIsGift.equals(1))
                    return "收入类型是赠送，服务只能选择赠送";
            } else if (orderType.equals(newType) || orderType.equals(renewType) || orderType.equals(extType) || orderType.equals(emdType)) {
                // 收入类型不是体验会员时，赠送服务时要有一个非赠送的服务
                if (containGift != 2) {
                    if (serviceIsGift.equals(1)) {
                        // 包含赠送服务
                        containGift = 1;
                    } else {
                        // 有正价服务
                        containGift = 2;
                    }
                }
            } else {
                return "请选择正确的收入类型";
            }

            String productUid = service.getProductUid();
            String productLogUid = service.getProductLogUid();
            if (StringUtils.isNotBlank(productUid)) {
                productUids.add(productUid);
                if (StringUtils.isNotBlank(productLogUid))
                    productLogUids.add(productLogUid);
            }
            projectUids.add(projectUid);
        }

        if (!orderType.equals(giftType) && !orderType.equals(expType) && containGift == 1)
            return "只有正价服务才能赠送服务";

        return "";
    }

    /**
     * 订单获取服务或关联服务
     */
    public static void getServiceListByOrderCode(
            String storeUid, List<CmorderDto> list
    ) {
        List<String> orderCodes = list.stream()
                .map(CmorderDto::getOrderCode)
                .filter(StringUtils::isNotBlank)
                .distinct()
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(orderCodes))
            return;

        List<SimpleCmserviceDto> serviceList = util.cmservicesService.simpleDtoListByOrderCodesAndStatusIn(storeUid, orderCodes);
        if (CollectionUtils.isEmpty(serviceList))
            return;

        Map<String, List<SimpleCmserviceDto>> map = serviceList.stream().collect(Collectors.groupingBy(SimpleCmserviceDto::getOrderCode));
        for (CmorderDto dto : list) {
            List<SimpleCmserviceDto> dtoList = map.get(dto.getOrderCode());
            if (CollectionUtils.isNotEmpty(dtoList))
                dto.setServiceList(dtoList);
        }
    }

    /**
     * 判断是否能排课且消耗课次
     */
    public static boolean isConsumeLesson(Integer lessonStatus, Integer freeStatus) {
        return lessonStatus.equals(1) && freeStatus.equals(1);
    }

    /**
     * 获取服务的名称+服务天数+活动次数
     */
    public static String getProductName(CmservicesDto service) {
        if (isConsumeLesson(service.getLessonStatus(), service.getFreeStatus())) {
            return service.getProductName() + "-" + service.getServiceDays() + "天" + "-" + service.getTotalLessons() + "次";
        } else {
            return service.getProductName() + "-" + service.getServiceDays() + "天";
        }
    }

    /**
     * 获取服务的名称+服务天数+活动次数
     */
    public static String getProductName(Cmservices service) {
        if (isConsumeLesson(service.getLessonStatus(), service.getFreeStatus())) {
            return service.getProductName() + "-" + service.getServiceDays() + "天" + "-" + service.getTotalLessons() + "次";
        } else {
            return service.getProductName() + "-" + service.getServiceDays() + "天";
        }
    }

    /**
     * 服务获取以活动次数，状态名称修改
     */
    public static void setUseLessonCntAndStatusName(
            List<CmservicesDto> serviceList, Map<String, Long> map
    ) {
        int openCardStatus = EnumType.ServiceStatus.OPEN_CARD.getStatus();
        int pauseCardStatus = EnumType.ServiceStatus.PAUSE_CARD.getStatus();
        int noChangeStatus = EnumType.ServiceStatus.NO_CHANGE.getStatus();
        for (CmservicesDto dto : serviceList) {
            if (isConsumeLesson(dto.getLessonStatus(), dto.getFreeStatus())) {
                // 设置已完结/已退费/已变更的状态名
                if (dto.getChangeStatus() != null && !dto.getChangeStatus().equals(noChangeStatus)) {
                    String changeName = dto.getChangeStatusName() + (dto.getChangeValue() != null ? dto.getChangeValue() + "次" : "");
                    dto.setStatusName(changeName);
                }
                // 获取服务已活动的次数
                if (map != null && dto.getStatus() != null && (dto.getStatus().equals(openCardStatus) || dto.getStatus().equals(pauseCardStatus)))
                    dto.setUseLessonCnt(NepUtil.nullToZero(map.get(dto.getUid())));
            } else {
                if (dto.getChangeStatus() != null && !dto.getChangeStatus().equals(noChangeStatus)) {
                    String changeName = dto.getChangeStatusName() + (dto.getChangeValue() != null ? dto.getChangeValue() + "天" : "");
                    dto.setStatusName(changeName);
                }
            }
        }
    }

    /**
     * 判断服务集合能否退费或变更
     */
    public static String judgeRefundServicesV2(
            List<Cmservices> servicesList, Date changDate, Map<String, Integer> refundNumMap
    ) {
        for (Cmservices service : servicesList) {
            Integer status = service.getStatus();
            Integer serviceChangeStatus = service.getChangeStatus();
            String productName = getProductName(service);

            // 判断变更状态
            if (serviceChangeStatus != null && !serviceChangeStatus.equals(EnumType.ServiceStatus.NO_CHANGE.getStatus())) {
                if (serviceChangeStatus.equals(refundStatus))
                    return productName + " 已退费，不能操作";
                else if (serviceChangeStatus.equals(invalidStatus))
                    return productName + " 已变更，不能操作";
                else if (serviceChangeStatus.equals(consumeStatus))
                    return productName + " 是消费记录，不能操作";
                else if (serviceChangeStatus.equals(changeStatus))
                    return productName + " 是变更记录，不能操作";
                else
                    return productName + " 未知错误，不能操作";
            }
            if (service.getEnding().equals(1))
                return productName + " 已结课，不能操作";

            // 已开卡服务，计算可退次数或天数; 未开卡服务，数量全退
            if (status != null && (status.equals(openCardStatus) || status.equals(pauseCardStatus))) {
                if (refundNumMap != null) {
                    int refundNum = NepUtil.nullToZero(refundNumMap.get(service.getUid()));
                    if (refundNum <= 0)
                        return productName + " 可退次数或天数必须大于0";

                    if (isConsumeLesson(service.getLessonStatus(), service.getFreeStatus())) {
                        // 可排活动且消耗活动次数的服务
                        int leftLessonNum = NepUtil.nullToZero(service.getLeftLessons());
                        if (leftLessonNum == 0)
                            return productName + " 的剩余活动次数为0，不能操作";

                        // 可退次数
                        if (refundNum > leftLessonNum)
                            return productName + " 的可退次数不能超过 " + leftLessonNum + "次";
                    } else {
                        // 按天计费的服务
                        if (changDate.getTime() < service.getBeginDate().getTime())
                            return productName + " 变更日期应大于开始日期";
                        if (changDate.getTime() >= service.getEndDate().getTime())
                            return productName + " 变更日期应小于结束日期";

                        // 根据结束日期和退费日期获取相差天数
                        int days = getDays(changDate, service.getEndDate());
                        if (refundNum > days)
                            return productName + " 的可退天数不能超过 " + days + "天";
                        service.setLeftDays(days);
                    }
                } else {
                    if (isConsumeLesson(service.getLessonStatus(), service.getFreeStatus())) {
                        // 可排活动且消耗活动次数的服务
                        int leftLessonNum = NepUtil.nullToZero(service.getLeftLessons());
                        if (leftLessonNum == 0)
                            return productName + " 的剩余活动次数为0，不能操作";
                    } else {
                        // 按天计费的服务
                        if (changDate.getTime() < service.getBeginDate().getTime())
                            return productName + " 变更日期应大于开始日期";
                        if (changDate.getTime() >= service.getEndDate().getTime())
                            return productName + " 变更日期应小于结束日期";

                        // 根据结束日期和退费日期获取相差天数
                        service.setLeftDays(getDays(changDate, service.getEndDate()));
                    }
                }
            }
        }
        return "";
    }

    /**
     * 判断服务集合能否退费或变更
     */
    public static String judgeChangeServicesV2(
            List<Cmservices> servicesList, Date changeDate
    ) {
        for (Cmservices service : servicesList) {
            Integer status = service.getStatus();
            Integer serviceChangeStatus = service.getChangeStatus();
            String productName = getProductName(service);

            // 判断变更状态
            if (serviceChangeStatus != null && !serviceChangeStatus.equals(EnumType.ServiceStatus.NO_CHANGE.getStatus())) {
                if (serviceChangeStatus.equals(refundStatus))
                    return productName + " 已退费，不能操作";
                else if (serviceChangeStatus.equals(invalidStatus))
                    return productName + " 已变更，不能操作";
                else if (serviceChangeStatus.equals(consumeStatus))
                    return productName + " 是消费记录，不能操作";
                else if (serviceChangeStatus.equals(changeStatus))
                    return productName + " 是变更记录，不能操作";
                else
                    return productName + " 未知错误，不能操作";
            }
            if (service.getEnding().equals(1))
                return productName + " 已结课，不能操作";

            // 已开卡服务，判断剩余活动次数或结束日期；未开卡的服务全变更
            if (status != null && (status.equals(openCardStatus) || status.equals(pauseCardStatus))) {
                if (isConsumeLesson(service.getLessonStatus(), service.getFreeStatus())) {
                    // 可排活动的服务
                    int leftLessonNum = NepUtil.nullToZero(service.getLeftLessons());
                    if (leftLessonNum == 0)
                        return productName + " 的剩余活动次数为0，不能操作";
                } else {
                    // 变更日期要小于服务的结束日期
                    if (changeDate.getTime() < service.getBeginDate().getTime())
                        return productName + " 变更日期要大于服务的开始日期";
                    if (changeDate.getTime() > service.getEndDate().getTime())
                        return productName + " 变更日期要小于服务的结束日期";
                }
            }
        }
        return "";
    }

    /**
     * 创建消耗服务记录和退费或变更服务记录
     */
    public static Map<Integer, List<Cmservices>> newConsumeAndRefundServiceListV2(
            Cmservices cmservices, String staffUid, String staffName, String storeName, String memberName,
            String newRefundOrderCode, String newTransferOrderCode, Date changeDateValue,
            String orderType, int refundNum
    ) {
        Map<Integer, List<Cmservices>> map = new HashMap<>();
        List<Cmservices> newServiceList = new ArrayList<>();
        List<Cmservices> newTransferServiceList = new ArrayList<>();
        if (isConsumeLesson(cmservices.getLessonStatus(), cmservices.getFreeStatus())) {
            // 按活动次数计费的服务

            // 创建消耗服务记录和退费服务记录
            int totalLessons = NepUtil.nullToZero(cmservices.getTotalLessons());
            int leftLessons = NepUtil.nullToZero(cmservices.getLeftLessons());

            // 按已消耗活动次数 创建消费服务记录
            int consumeLesson = totalLessons;
            if (totalLessons >= leftLessons)
                consumeLesson = totalLessons - leftLessons;
            Cmservices consumeService = newConsumeAndRefundServiceV2(
                    cmservices, storeName, memberName, staffUid, staffName, newRefundOrderCode, orderType,
                    changeDateValue, consumeStatus, consumeName, consumeLesson, 0
            );
            newServiceList.add(consumeService);

            // 按申请次数 创建退费服务记录
            Cmservices refundService = newConsumeAndRefundServiceV2(
                    cmservices, storeName, memberName, staffUid, staffName, newRefundOrderCode, orderType,
                    changeDateValue, refundStatus, refundName, refundNum, 0
            );
            newServiceList.add(refundService);

            // 如果未消耗的次数大于申请退费次数，创建未开卡的剩余服务记录
            if (leftLessons > refundNum) {
                int surplusNum = leftLessons - refundNum;
                Cmservices surplusService = newNoCardServiceV2(
                        cmservices, storeName, memberName, staffUid, staffName,
                        newTransferOrderCode, cmservices.getOrderCode(), surplusNum, null
                );
                newTransferServiceList.add(surplusService);
            }
        } else {
            // 按活动天数计费的服务

            // 按已活动天数 创建消耗服务记录
            int consumeDay = NepUtil.nullToZero(cmservices.getServiceDays());
            int surplusDay = 0;
            // 服务的结束日期大于变更日期
            if (cmservices.getEndDate().getTime() >= changeDateValue.getTime()) {
                consumeDay = getDays(cmservices.getBeginDate(), changeDateValue);
                surplusDay = getDays(changeDateValue, cmservices.getEndDate());
            }

            Cmservices consumeService = newConsumeAndRefundServiceV2(
                    cmservices, storeName, memberName, staffUid, staffName, newRefundOrderCode, orderType,
                    changeDateValue, consumeStatus, consumeName, consumeDay, null
            );
            newServiceList.add(consumeService);

            // 按申请天数 创建退费服务记录
            Cmservices refundService = newConsumeAndRefundServiceV2(
                    cmservices, storeName, memberName, staffUid, staffName, newRefundOrderCode, orderType,
                    changeDateValue, refundStatus, refundName, refundNum, null
            );
            newServiceList.add(refundService);

            // 如果未消耗的天数大于申请退费天数， 创建未开卡的剩余服务记录
            if (surplusDay > refundNum) {
                int surplusNum = surplusDay - refundNum;
                Cmservices surplusService = newNoCardServiceV2(
                        cmservices, storeName, memberName, staffUid, staffName,
                        newTransferOrderCode, cmservices.getOrderCode(), null, surplusNum
                );
                newTransferServiceList.add(surplusService);
            }
        }
        map.put(0, newServiceList);
        map.put(1, newTransferServiceList);
        return map;
    }

    public static Map<Integer, List<Cmservices>> newRefundServiceListV3(
            Cmservices cmservices, String staffUid, String staffName, String storeName, String memberName,
            String newRefundOrderCode, String newTransferOrderCode, Date changeDateValue,
            String orderType, Integer refundNum
    ) {
        Map<Integer, List<Cmservices>> map = new HashMap<>();
        List<Cmservices> newServiceList = new ArrayList<>();
        List<Cmservices> newTransferServiceList = new ArrayList<>();
        if (isConsumeLesson(cmservices.getLessonStatus(), cmservices.getFreeStatus())) {
            // 按活动次数计费的服务

            refundNum = refundNum != null ? refundNum : cmservices.getLeftLessons();
            // 创建退费服务记录
            int leftLessons = NepUtil.nullToZero(cmservices.getLeftLessons());
            if (leftLessons > 0) {
                // 按申请次数 创建退费服务记录
                Cmservices refundService = newRefundServiceV3(
                        cmservices, storeName, memberName, staffUid, staffName, newRefundOrderCode, orderType,
                        changeDateValue, refundStatus, refundName, refundNum
                );
                newServiceList.add(refundService);

                // 如果未消耗的次数大于申请退费次数，创建未开卡的剩余服务记录
                if (leftLessons > refundNum) {
                    int surplusNum = leftLessons - refundNum;
                    Cmservices surplusService = newNoCardServiceV2(
                            cmservices, storeName, memberName, staffUid, staffName,
                            newTransferOrderCode, cmservices.getOrderCode(), surplusNum, null
                    );
                    newTransferServiceList.add(surplusService);
                }
            }
        } else {
            // 按活动天数计费的服务

            refundNum = refundNum != null ? refundNum : cmservices.getLeftDays();
            // 按已活动天数 创建消耗服务记录
            int surplusDay = 0;
            // 服务的结束日期大于变更日期
            if (cmservices.getEndDate().getTime() >= changeDateValue.getTime()) {
                surplusDay = getDays(changeDateValue, cmservices.getEndDate());
            }

            if (surplusDay > 0) {
                // 按申请天数 创建退费服务记录
                Cmservices refundService = newRefundServiceV3(
                        cmservices, storeName, memberName, staffUid, staffName, newRefundOrderCode, orderType,
                        changeDateValue, refundStatus, refundName, refundNum
                );
                newServiceList.add(refundService);

                // 如果未消耗的天数大于申请退费天数， 创建未开卡的剩余服务记录
                if (surplusDay > refundNum) {
                    int surplusNum = surplusDay - refundNum;
                    Cmservices surplusService = newNoCardServiceV2(
                            cmservices, storeName, memberName, staffUid, staffName,
                            newTransferOrderCode, cmservices.getOrderCode(), null, surplusNum
                    );
                    newTransferServiceList.add(surplusService);
                }
            }
        }
        map.put(0, newServiceList);
        map.put(1, newTransferServiceList);
        return map;
    }

    /**
     * 创建消耗服务记录和退费或变更服务记录
     */
    public static List<Cmservices> newConsumeAndChangeServiceListV2(
            Cmservices service, String staffUid, String staffName, String storeName, String memberName,
            String newOrderCode, String orderType, Date changeDateValue
    ) {
        List<Cmservices> newServiceList = new ArrayList<>();
        // 如果已开卡，创建消耗服务记录和退费服务记录
        if (isConsumeLesson(service.getLessonStatus(), service.getFreeStatus())) {
            // 可排活动且消耗活动次数的服务
            int totalLessons = NepUtil.nullToZero(service.getTotalLessons());
            int leftLessons = NepUtil.nullToZero(service.getLeftLessons());

            // 创建消耗服务记录按已活动次数
            int consumeLesson = totalLessons;
            if (totalLessons >= leftLessons)
                consumeLesson = totalLessons - leftLessons;
            Cmservices consumeData = newConsumeAndRefundOrChangeServiceV2(
                    service, storeName, memberName, staffUid, staffName, newOrderCode, orderType,
                    changeDateValue, consumeStatus, consumeName, consumeLesson, 0, null, null
            );
            newServiceList.add(consumeData);

            // 创建退费/变更服务记录按剩余活动次数
            Cmservices refundData = newConsumeAndRefundOrChangeServiceV2(
                    service, storeName, memberName, staffUid, staffName, newOrderCode, orderType,
                    changeDateValue, changeStatus, changeName, leftLessons, 0, null, null
            );
            newServiceList.add(refundData);
        } else {
            // 不可排活动或不消耗活动次数的服务
            int consumeDay = NepUtil.nullToZero(service.getServiceDays());
            int surplusDay = 0;
            // 服务的结束日期大于变更日期
            if (service.getEndDate().getTime() >= changeDateValue.getTime()) {
                consumeDay = getDays(service.getBeginDate(), changeDateValue);
                surplusDay = getDays(changeDateValue, service.getEndDate());
            }
            // 创建消耗服务记录按已活动天数
            Cmservices consumeData = newConsumeAndRefundOrChangeServiceV2(
                    service, storeName, memberName, staffUid, staffName, newOrderCode, orderType,
                    changeDateValue, consumeStatus, consumeName, consumeDay, null, null, changeDateValue
            );
            newServiceList.add(consumeData);

            // 创建退费/变更服务记录按剩余活动天数
            Cmservices refundData = newConsumeAndRefundOrChangeServiceV2(
                    service, storeName, memberName, staffUid, staffName, newOrderCode, orderType,
                    changeDateValue, changeStatus, changeName, surplusDay, null, changeDateValue, null
            );
            newServiceList.add(refundData);
        }
        return newServiceList;
    }

    public static List<Cmservices> newChangeServiceListV3(
            Cmservices service, String staffUid, String staffName, String storeName, String memberName,
            String newOrderCode, String orderType, Date changeDateValue
    ) {
        List<Cmservices> newServiceList = new ArrayList<>();
        // 如果已开卡，创建消耗服务记录和退费服务记录
        if (isConsumeLesson(service.getLessonStatus(), service.getFreeStatus())) {
            // 可排活动且消耗活动次数的服务
            int leftLessons = NepUtil.nullToZero(service.getLeftLessons());

            if (leftLessons > 0) {
                // 创建退费/变更服务记录按剩余活动次数
                Cmservices refundData = newRefundOrChangeServiceV3(
                        service, storeName, memberName, staffUid, staffName, newOrderCode, orderType,
                        changeDateValue, changeStatus, changeName, leftLessons, null, null
                );
                newServiceList.add(refundData);
            }
        } else {
            // 不可排活动或不消耗活动次数的服务
            int surplusDay = 0;
            // 服务的结束日期大于变更日期
            if (service.getEndDate().getTime() >= changeDateValue.getTime()) {
                surplusDay = getDays(changeDateValue, service.getEndDate());
            }

            if (surplusDay > 0) {
                // 创建退费/变更服务记录按剩余活动天数
                Cmservices refundData = newRefundOrChangeServiceV3(
                        service, storeName, memberName, staffUid, staffName, newOrderCode, orderType,
                        changeDateValue, changeStatus, changeName, surplusDay, changeDateValue, null
                );
                newServiceList.add(refundData);
            }
        }
        return newServiceList;
    }

    /**
     * 会员订单服务详情
     */
    private static Cmservices newConsumeAndRefundOrChangeServiceV2(
            Cmservices service, String storeName, String memberName, String staffUid, String staffName,
            String newOrderCode, String orderType, Date changeDate, Integer changeStatus, String changeStatusName,
            Integer changeValue, Integer leftLessons, Date beginDate, Date endDate
    ) {
        Cmservices data = new Cmservices();
        data.setChangeDate(changeDate);
        data.setChangeStatus(changeStatus);
        data.setChangeStatusName(changeStatusName);
        if (null != changeValue)
            data.setChangeValue(changeValue);
        if (null != leftLessons)
            data.setLeftLessons(leftLessons);
        if (null != beginDate)
            data.setBeginDate(beginDate);
        else
            data.setBeginDate(service.getBeginDate());
        if (null != endDate)
            data.setEndDate(endDate);
        else
            data.setEndDate(service.getEndDate());

        data.setUid(KitUtil.getUuid());
        data.setOrderCode(service.getOrderCode());
        data.setRelationServiceUid(service.getUid());
        data.setRelationCode(newOrderCode);

        data.setProductCode(service.getProductCode());
        data.setProductName(service.getProductName());
        data.setServiceDays(service.getServiceDays());
        data.setServiceCycle(service.getServiceCycle());
        data.setCycleName(service.getCycleName());
        data.setLeftDays(service.getLeftDays());
        data.setIsGift(service.getIsGift());
        data.setTotalLessons(service.getTotalLessons());
        data.setCorpUid(service.getCorpUid());
        data.setStoreUid(service.getStoreUid());
        data.setStoreName(storeName);
        data.setFromStoreUid(service.getStoreUid());
        data.setFromStoreName(storeName);
        data.setOrderType(orderType);
        data.setMemberUid(service.getMemberUid());
        data.setMemberName(memberName);
        data.setAddStaffUid(staffUid);
        data.setAddStaffName(staffName);
        data.setLastStaffUid(staffUid);
        data.setLastStaffName(staffName);

        data.setLessonStatus(service.getLessonStatus());
        data.setFreeStatus(service.getFreeStatus());
        data.setProjectUid(service.getProjectUid());
        data.setProductUid(service.getProductUid());
        data.setProductLogUid(service.getProductLogUid());
        data.setStoreProductName(service.getStoreProductName());
        data.setProductType(service.getProductType());

        data.setUnitAmount(service.getUnitAmount());
        return data;
    }

    /**
     * 会员订单服务详情
     */
    private static Cmservices newRefundOrChangeServiceV3(
            Cmservices service, String storeName, String memberName, String staffUid, String staffName,
            String newOrderCode, String orderType, Date changeDate, Integer changeStatus, String changeStatusName,
            Integer changeValue, Date beginDate, Date endDate
    ) {
        Cmservices data = new Cmservices();
        data.setChangeDate(changeDate);
        data.setChangeStatus(changeStatus);
        data.setChangeStatusName(changeStatusName);
        if (null != changeValue)
            data.setChangeValue(changeValue);
        if (null != beginDate)
            data.setBeginDate(beginDate);
        else
            data.setBeginDate(service.getBeginDate());
        if (null != endDate)
            data.setEndDate(endDate);
        else
            data.setEndDate(service.getEndDate());

        data.setUid(KitUtil.getUuid());
        data.setOrderCode(service.getOrderCode());
        data.setRelationServiceUid(service.getUid());
        data.setRelationCode(newOrderCode);

        data.setProductCode(service.getProductCode());
        data.setProductName(service.getProductName());
        data.setServiceCycle(service.getServiceCycle());
        data.setCycleName(service.getCycleName());
        data.setIsGift(service.getIsGift());
        data.setServiceDays(service.getServiceDays());
        data.setLeftDays(null);
        data.setTotalLessons(service.getTotalLessons());
        data.setLeftLessons(service.getTotalLessons());

        data.setCorpUid(service.getCorpUid());
        data.setStoreUid(service.getStoreUid());
        data.setStoreName(storeName);
        data.setFromStoreUid(service.getStoreUid());
        data.setFromStoreName(storeName);
        data.setOrderType(orderType);
        data.setMemberUid(service.getMemberUid());
        data.setMemberName(memberName);
        data.setAddStaffUid(staffUid);
        data.setAddStaffName(staffName);
        data.setLastStaffUid(staffUid);
        data.setLastStaffName(staffName);

        data.setLessonStatus(service.getLessonStatus());
        data.setFreeStatus(service.getFreeStatus());
        data.setProjectUid(service.getProjectUid());
        data.setProductUid(service.getProductUid());
        data.setProductLogUid(service.getProductLogUid());
        data.setStoreProductName(service.getStoreProductName());
        data.setProductType(service.getProductType());

        data.setUnitAmount(service.getUnitAmount());
        return data;
    }

    /**
     * 会员订单服务详情
     */
    private static Cmservices newConsumeAndRefundServiceV2(
            Cmservices service, String storeName, String memberName, String staffUid, String staffName,
            String newOrderCode, String orderType, Date changeDate, Integer changeStatus, String changeStatusName,
            Integer changeValue, Integer leftLessons
    ) {
        Cmservices data = new Cmservices();
        data.setChangeDate(changeDate);
        data.setChangeStatus(changeStatus);
        data.setChangeStatusName(changeStatusName);

        if (null != changeValue)
            data.setChangeValue(changeValue);

        data.setUid(KitUtil.getUuid());
        data.setOrderCode(service.getOrderCode());
        data.setRelationServiceUid(service.getUid());
        data.setRelationCode(newOrderCode);

        data.setTotalLessons(service.getTotalLessons());
        if (null != leftLessons)
            data.setLeftLessons(leftLessons);
        data.setServiceDays(service.getServiceDays());
        data.setLeftDays(service.getLeftDays());

        data.setBeginDate(service.getBeginDate());
        data.setEndDate(service.getEndDate());

        data.setProductCode(service.getProductCode());
        data.setProductName(service.getProductName());
        data.setServiceCycle(service.getServiceCycle());
        data.setCycleName(service.getCycleName());
        data.setIsGift(service.getIsGift());
        data.setCorpUid(service.getCorpUid());
        data.setStoreUid(service.getStoreUid());
        data.setStoreName(storeName);
        data.setFromStoreUid(service.getStoreUid());
        data.setFromStoreName(storeName);
        data.setOrderType(orderType);
        data.setMemberUid(service.getMemberUid());
        data.setMemberName(memberName);
        data.setAddStaffUid(staffUid);
        data.setAddStaffName(staffName);
        data.setLastStaffUid(staffUid);
        data.setLastStaffName(staffName);

        data.setLessonStatus(service.getLessonStatus());
        data.setFreeStatus(service.getFreeStatus());
        data.setProjectUid(service.getProjectUid());
        data.setProductUid(service.getProductUid());
        data.setProductLogUid(service.getProductLogUid());
        data.setStoreProductName(service.getStoreProductName());
        data.setProductType(service.getProductType());

        data.setUnitAmount(service.getUnitAmount());
        return data;
    }

    /**
     * 会员订单服务详情
     */
    private static Cmservices newRefundServiceV3(
            Cmservices service, String storeName, String memberName, String staffUid, String staffName,
            String newOrderCode, String orderType, Date changeDate, Integer changeStatus, String changeStatusName, Integer changeValue
    ) {
        Cmservices data = new Cmservices();
        data.setChangeDate(changeDate);
        data.setChangeStatus(changeStatus);
        data.setChangeStatusName(changeStatusName);

        if (null != changeValue)
            data.setChangeValue(changeValue);

        data.setUid(KitUtil.getUuid());
        data.setOrderCode(service.getOrderCode());
        data.setRelationServiceUid(service.getUid());
        data.setRelationCode(newOrderCode);

        data.setTotalLessons(service.getTotalLessons());
        data.setLeftLessons(service.getTotalLessons());
        data.setServiceDays(service.getServiceDays());
        data.setLeftDays(null);

        data.setBeginDate(service.getBeginDate());
        data.setEndDate(service.getEndDate());

        data.setProductCode(service.getProductCode());
        data.setProductName(service.getProductName());
        data.setServiceCycle(service.getServiceCycle());
        data.setCycleName(service.getCycleName());
        data.setIsGift(service.getIsGift());
        data.setCorpUid(service.getCorpUid());
        data.setStoreUid(service.getStoreUid());
        data.setStoreName(storeName);
        data.setFromStoreUid(service.getStoreUid());
        data.setFromStoreName(storeName);
        data.setOrderType(orderType);
        data.setMemberUid(service.getMemberUid());
        data.setMemberName(memberName);
        data.setAddStaffUid(staffUid);
        data.setAddStaffName(staffName);
        data.setLastStaffUid(staffUid);
        data.setLastStaffName(staffName);

        data.setLessonStatus(service.getLessonStatus());
        data.setFreeStatus(service.getFreeStatus());
        data.setProjectUid(service.getProjectUid());
        data.setProductUid(service.getProductUid());
        data.setProductLogUid(service.getProductLogUid());
        data.setStoreProductName(service.getStoreProductName());
        data.setProductType(service.getProductType());

        data.setUnitAmount(service.getUnitAmount());
        return data;
    }


    /**
     * 新建退费的会员服务订单
     */
    public static Cmorders newRefundCmorder(
            String corpUid, String storeUid, String storeName, String staffUid, String staffName,
            String memberUid, String memberName, String orderCode, Double orderAmount,
            Date orderDate, String orderRemark, String relationCode
    ) {
        Cmorders data = new Cmorders();
        data.setOrderCode(orderCode);
        data.setCorpUid(corpUid);
        data.setStoreUid(storeUid);
        data.setStoreName(storeName);
        data.setMemberUid(memberUid);
        data.setMemberName(memberName);
        data.setAddStaffUid(staffUid);
        data.setAddStaffName(staffName);
        data.setLastStaffUid(staffUid);
        data.setLastStaffName(staffName);
        data.setStatus(1);
        data.setStatusName("审批通过");
        // 退费
        data.setInoutType(2);
        data.setInoutTypeName("支出");
        data.setOrderType(EnumType.OrderType.REFUND.getType());
        data.setRelationCode(relationCode);
        data.setOrderState(EnumType.CmOrderState.REFUND.getState());
        data.setOrderStateName(EnumType.CmOrderState.REFUND.getName());
        // 退款金额转为负数
        if (orderAmount > 0)
            orderAmount = -orderAmount;
        data.setOrderAmount(orderAmount);
        data.setOrderRemark(NepUtil.nullToZero(orderRemark));
        data.setOrderDate(orderDate);
        data.setSaleStaffUid(staffUid);
        data.setSaleStaffFullName(staffName);
        return data;
    }

    /**
     * 新建变更的会员服务订单
     */
    public static Cmorders newChangeCmorder(
            String corpUid, String storeUid, String storeName, String staffUid, String staffName,
            String newOrderCode, String memberUid, String memberName,
            String saleStaffUid, String saleStaffFullName, String saleStaffPriPhone,
            String saleStaffPubPhone, String saleStaffNickName, String contractCode,
            Double orderAmount, Date orderDate, String giftGotten, String giftRemark,
            String orderRemark, String payChannelCode, String orderType, String relationCode, Double carriedForwardAmount,
            Integer serviceNum
    ) throws Exception {
        Cmorders data = new Cmorders();
        data.setOrderCode(newOrderCode);
        data.setCorpUid(corpUid);
        data.setStoreUid(storeUid);
        data.setStoreName(storeName);
        data.setMemberUid(memberUid);
        data.setMemberName(memberName);
        data.setAddStaffUid(staffUid);
        data.setAddStaffName(staffName);
        data.setStatus(0);
        data.setStatusName("待审批");
        // 变更
        data.setInoutType(1);
        data.setInoutTypeName("收入");
        data.setRelationCode(relationCode);
        data.setOrderState(2);
        data.setOrderStateName("变更");
        data.setServiceNum(serviceNum);
        data.setOrderType(NepUtil.nullToZero(orderType));
        data.setContractCode(NepUtil.nullToZero(contractCode));
        data.setOrderAmount(NepUtil.nullToZero(orderAmount));
        data.setGiftGotten(NepUtil.nullToZero(giftGotten));
        data.setGiftRemark(NepUtil.nullToZero(giftRemark));
        data.setPayChannelCode(NepUtil.nullToZero(payChannelCode));
        data.setOrderDate(orderDate);
        data.setSaleStaffUid(NepUtil.nullToZero(saleStaffUid));
        data.setSaleStaffFullName(NepUtil.nullToZero(saleStaffFullName));
        data.setSaleStaffPriPhone(NepUtil.nullToZero(saleStaffPriPhone));
        data.setSaleStaffPubPhone(NepUtil.nullToZero(saleStaffPubPhone));
        data.setSaleStaffNickName(NepUtil.nullToZero(saleStaffNickName));

        data.setLastStaffUid(staffUid);
        data.setLastStaffName(staffName);
        data.setOrderRemark(NepUtil.nullToZero(orderRemark));

        data.setCarriedForwardAmount(carriedForwardAmount);

        return data;
    }

    /**
     * 创建变更服务记录
     */
    public static Cmservices newChangeService(
            Cmservices service, StoreProjects storeProject, String orderCode, String orderType,
            String corpUid, String storeUid, String storeName, String memberUid, String memberName, String staffUid, String staffName
    ) {
        service.setCorpUid(corpUid);
        service.setStoreUid(storeUid);
        service.setStoreName(storeName);
        service.setFromStoreUid(storeUid);
        service.setFromStoreName(storeName);
        service.setMemberUid(memberUid);
        service.setMemberName(memberName);
        service.setAddStaffUid(staffUid);
        service.setAddStaffName(staffName);
        service.setLastStaffUid(staffUid);
        service.setLastStaffName(staffName);

        service.setUid(KitUtil.getUuid());
        service.setOrderCode(orderCode);
        service.setOrderType(orderType);
        service.setStatus(EnumType.ServiceStatus.NO_CARD.getStatus());
        service.setStatusName(EnumType.ServiceStatus.NO_CARD.getName());
        service.setChangeStatus(EnumType.ServiceStatus.NO_CHANGE.getStatus());
        service.setEnding(0);
        service.setEndingType(0);
        service.setEndingTime(null);
        service.setEndingRemark(null);

        if (service.getTotalLessons() != null)
            service.setLeftLessons(service.getTotalLessons());
        if (service.getServiceDays() != null)
            service.setLeftDays(service.getServiceDays());

        service.setLessonStatus(storeProject.getLessonStatus());
        service.setFreeStatus(storeProject.getFreeStatus());
        service.setProjectUid(storeProject.getUid());
        service.setProductCode(storeProject.getId() + "");
        service.setProductName(storeProject.getProjectName());

        service.setProductUid(null);
        service.setProductLogUid(null);
        service.setStoreProductName(null);
        service.setProductType(null);

        return service;
    }

    /**
     * 会员订单服务详情
     */
    private static Cmservices newNoCardServiceV2(
            Cmservices service, String storeName, String memberName, String staffUid, String staffName,
            String newOrderCode, String relationCode, Integer totalLessonNum, Integer serviceDays
    ) {
        Cmservices newService = new Cmservices();
        newService.setCorpUid(service.getCorpUid());
        newService.setStoreUid(service.getStoreUid());
        newService.setStoreName(storeName);
        newService.setFromStoreUid(service.getStoreUid());
        newService.setFromStoreName(storeName);
        newService.setMemberUid(service.getMemberUid());
        newService.setMemberName(memberName);
        newService.setAddStaffUid(staffUid);
        newService.setAddStaffName(staffName);
        newService.setLastStaffUid(staffUid);
        newService.setLastStaffName(staffName);

        newService.setUid(KitUtil.getUuid());
        newService.setOrderCode(newOrderCode);
        newService.setOrderType(service.getOrderType());
        newService.setStatus(EnumType.ServiceStatus.NO_CARD.getStatus());
        newService.setStatusName(EnumType.ServiceStatus.NO_CARD.getName());
        newService.setChangeStatus(EnumType.ServiceStatus.NO_CHANGE.getStatus());
        newService.setEnding(0);
        newService.setEndingType(0);
        newService.setEndingTime(null);
        newService.setEndingRemark(null);

        if (totalLessonNum != null) {
            newService.setServiceDays(service.getServiceDays());
            newService.setTotalLessons(totalLessonNum);
            newService.setLeftLessons(totalLessonNum);
        }
        if (serviceDays != null) {
            newService.setServiceDays(serviceDays);
            newService.setLeftDays(serviceDays);
        }

        newService.setRelationServiceUid(service.getUid());
        newService.setRelationCode(relationCode);

        newService.setServiceCycle(service.getServiceCycle());
        newService.setCycleName(service.getCycleName());
        newService.setIsGift(service.getIsGift());

        newService.setLessonStatus(service.getLessonStatus());
        newService.setFreeStatus(service.getFreeStatus());
        newService.setProjectUid(service.getProjectUid());
        newService.setProductCode(service.getProductCode());
        newService.setProductName(service.getProductName());

        newService.setProductUid(service.getProductUid());
        newService.setProductLogUid(service.getProductLogUid());
        newService.setStoreProductName(service.getStoreProductName());
        newService.setProductType(service.getProductType());

        newService.setUnitAmount(service.getUnitAmount());
        return newService;
    }

    /**
     * 创建变更服务记录
     */
    public static Cmservices copyService(
            Cmservices service, Date changeDateValue,
            String orderCode, String orderType, String corpUid, String storeUid, String storeName,
            String memberUid, String memberName, String staffUid, String staffName
    ) {
        Cmservices newService = new Cmservices();

        if (service.getStatus().equals(openCardStatus) || service.getStatus().equals(pauseCardStatus)) {
            // 已开卡
            if (isConsumeLesson(service.getLessonStatus(), service.getFreeStatus())) {
                // 按次数
                newService.setServiceDays(service.getServiceDays());
                Integer leftLessons = service.getLeftLessons();
                // 剩余次数为0则不复制服务
                if (leftLessons == null || leftLessons <= 0)
                    return null;
                newService.setTotalLessons(leftLessons);
                newService.setLeftLessons(leftLessons);
            } else {
                // 按天数
                int surplusDay = getDays(changeDateValue, service.getEndDate());
                // 剩余天数为0则不复制服务
                if (surplusDay <= 0)
                    return null;
                newService.setServiceDays(surplusDay);
                newService.setLeftDays(surplusDay);
            }
        } else {
            // 未开卡
            newService.setServiceDays(service.getServiceDays());
            newService.setTotalLessons(service.getTotalLessons());
            if (isConsumeLesson(service.getLessonStatus(), service.getFreeStatus())) {
                newService.setLeftLessons(service.getTotalLessons());
            } else {
                newService.setLeftDays(service.getServiceDays());
            }
        }

        newService.setCorpUid(corpUid);
        newService.setStoreUid(storeUid);
        newService.setStoreName(storeName);
        newService.setFromStoreUid(storeUid);
        newService.setFromStoreName(storeName);
        newService.setMemberUid(memberUid);
        newService.setMemberName(memberName);
        newService.setAddStaffUid(staffUid);
        newService.setAddStaffName(staffName);
        newService.setLastStaffUid(staffUid);
        newService.setLastStaffName(staffName);

        newService.setUid(KitUtil.getUuid());
        newService.setOrderCode(orderCode);
        newService.setOrderType(orderType);
        newService.setStatus(service.getStatus());
        newService.setStatusName(service.getStatusName());
        newService.setChangeStatus(service.getChangeStatus());
        newService.setEnding(0);
        newService.setEndingType(0);
        newService.setEndingTime(null);
        newService.setEndingRemark(null);

        newService.setLessonStatus(service.getLessonStatus());
        newService.setFreeStatus(service.getFreeStatus());
        newService.setProjectUid(service.getProjectUid());
        newService.setProductCode(service.getProductCode());
        newService.setProductName(service.getProductName());

        newService.setBeginDate(service.getBeginDate());
        newService.setEndDate(service.getEndDate());
        newService.setIsGift(service.getIsGift());
        newService.setStaffUid(service.getStaffUid());
        newService.setStaffFullName(service.getStaffFullName());
        newService.setStaffNickName(service.getStaffNickName());
        newService.setStaffPriPhone(service.getStaffPriPhone());

        newService.setProductUid(null);
        newService.setProductLogUid(null);
        newService.setStoreProductName(null);
        newService.setProductType(null);

        return newService;
    }

    /**
     * 复制订单
     */
    public static Cmorders copyCmorder(
            Cmorders cmorders, String newCmorderOrderCode, double carriedForwardAmount, double orderAmount
    ) {
        Cmorders newCmorder = new Cmorders();
        BeanUtils.copyProperties(cmorders, newCmorder);
        if (newCmorder.getId() > 0) {
            newCmorder.setId(null);
            newCmorder.setOrderCode(newCmorderOrderCode);
            newCmorder.setOrderRemark(cmorders.getOrderCode() + "申请退费，将结余或未选择退费的服务转移至此订单。");
            newCmorder.setOrderState(EnumType.CmOrderState.CHANGE.getState());
            newCmorder.setOrderStateName(EnumType.CmOrderState.CHANGE.getName());
            newCmorder.setRelationCode(cmorders.getOrderCode());
            newCmorder.setStatus(0);
            newCmorder.setStatusName("待审批");
            newCmorder.setOrderAmount(0d);
            // 剩余结余金额=结转金额-退款金额
            double sub = DoubleUtil.sub(carriedForwardAmount, orderAmount);
            if (sub > 0) {
                newCmorder.setCarriedForwardAmount(sub);
            } else {
                newCmorder.setCarriedForwardAmount(0d);
            }
        }
        return newCmorder;
    }

    /**
     * 已开卡且可排活动的服务uid集合，获取消耗数量
     */
    public static Map<String, Long> getConsumeLessonMapByDto(
            List<CmservicesDto> servicesList
    ) {
        // 已开卡、可排活动、消耗活动次数的服务uid集合，查询消课数量
        List<String> consumeUidList = servicesList.stream()
                .filter(service -> service.getLessonStatus().equals(1) && service.getFreeStatus().equals(1)
                        && service.getStatus() != null && (service.getStatus().equals(openCardStatus) || service.getStatus().equals(pauseCardStatus)))
                .map(CmservicesDto::getUid)
                .collect(Collectors.toList());

        Map<String, Long> consumeMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(consumeUidList))
            consumeMap = util.caCallNameService.getCntByServiceUids(consumeUidList);
        return consumeMap;
    }

    /**
     * 原订单的结转金额
     */
    public static double getCarriedForwardAmountV2(List<Cmservices> servicesList, Date changeDateValue) {
        double carriedForwardAmount = 0;
        for (Cmservices service : servicesList) {
            double amount = 0;
            double unitAmount = NepUtil.nullToZero(service.getUnitAmount());
            if (unitAmount > 0) {
                Integer status = service.getStatus();
                if (status.equals(openCardStatus) || status.equals(pauseCardStatus)) {
                    if (CmorderUtil.isConsumeLesson(service.getLessonStatus(), service.getFreeStatus())) {
                        // 按剩余次数
                        Integer leftLessons = service.getLeftLessons();
                        if (leftLessons == null || leftLessons <= 0)
                            continue;
                        amount = DoubleUtil.mul(leftLessons, unitAmount, 2);
                    } else {
                        // 按剩余天数
                        if (changeDateValue.getTime() >= service.getEndDate().getTime())
                            continue;
                        int days = getDays(changeDateValue, service.getEndDate());
                        amount = DoubleUtil.mul(days, unitAmount, 2);
                    }
                } else {
                    amount = NepUtil.nullToZero(service.getTotalAmount());
                }
            }
            carriedForwardAmount = DoubleUtil.sum(carriedForwardAmount, amount);
        }
        return carriedForwardAmount;
    }


    /**
     * 获取2个日期相差的天数
     */
    private static int getDays(Date changDate, Date endDate) {
        if (endDate.getTime() > changDate.getTime()) {
            long days = DateUtil.differentDays(changDate, endDate);
            return (int) days;
        }
        return 0;
    }

    /**
     * 设置周期并禁用没有周期的服务
     */
    public static List<StoreProjectsDtoV2> setCycleList(boolean selfStore, String storeUid, List<StoreProjectsDtoV2> list) {
        if (CollectionUtils.isEmpty(list))
            return new ArrayList<>();

        List<String> projectUidList = list.stream().map(StoreProjectsDtoV2::getUid).collect(Collectors.toList());
        List<StoreProjectCycleDtoV3> cycleList = util.cycleService.configListByStoreUidAndProjectUidIn(selfStore, storeUid, projectUidList);
        if (CollectionUtils.isEmpty(cycleList)) {
            for (StoreProjectsDtoV2 dto : list)
                dto.setEnabled(0);
            return list;
        }

        LinkedHashMap<String, List<StoreProjectCycleDtoV3>> cycleMap = cycleList.stream()
                .collect(Collectors.groupingBy(StoreProjectCycleDtoV3::getProjectUid, LinkedHashMap::new, Collectors.toList()));
        for (StoreProjectsDtoV2 dto : list) {
            List<StoreProjectCycleDtoV3> cycleDtoList = cycleMap.get(dto.getUid());
            if (CollectionUtils.isNotEmpty(cycleDtoList)) {
                dto.setEnabled(1);
                dto.setCycleList(cycleDtoList);
            } else {
                dto.setEnabled(0);
            }
        }

        // 按启用字段降序
        return list.stream()
                .sorted(Comparator.comparing(StoreProjectsDtoV2::getEnabled).reversed())
                .collect(Collectors.toList());
    }

    /**
     * 设置阶段并禁用没有周期的服务
     */
    public static List<StoreProjectsDtoV2> setStageList(boolean selfStore, String storeUid, List<StoreProjectsDtoV2> list) {
        if (CollectionUtils.isEmpty(list))
            return new ArrayList<>();

        List<String> projectUidList = list.stream().map(StoreProjectsDtoV2::getUid).collect(Collectors.toList());
        List<String> enableProjectUidList = new ArrayList<>();
        // 设置周期
        List<StoreProjectCycleDtoV3> cycleList = util.cycleService.configListByStoreUidAndProjectUidIn(selfStore, storeUid, projectUidList);
        if (CollectionUtils.isEmpty(cycleList)) {
            for (StoreProjectsDtoV2 dto : list)
                dto.setEnabled(0);
            return list;
        } else {
            LinkedHashMap<String, List<StoreProjectCycleDtoV3>> cycleMap = cycleList.stream()
                    .collect(Collectors.groupingBy(StoreProjectCycleDtoV3::getProjectUid, LinkedHashMap::new, Collectors.toList()));
            for (StoreProjectsDtoV2 dto : list) {
                List<StoreProjectCycleDtoV3> cycleDtoList = cycleMap.get(dto.getUid());
                if (CollectionUtils.isNotEmpty(cycleDtoList)) {
                    dto.setEnabled(1);
                    enableProjectUidList.add(dto.getUid());
                } else {
                    dto.setEnabled(0);
                }
            }
        }

        // 设置阶段
        List<StoreProjectStageDto> stageList = util.stageService.listByProjectUidIn(enableProjectUidList);
        if (CollectionUtils.isNotEmpty(stageList)) {
            LinkedHashMap<String, List<StoreProjectStageDto>> stageMap = stageList.stream()
                    .collect(Collectors.groupingBy(StoreProjectStageDto::getProjectUid, LinkedHashMap::new, Collectors.toList()));
            for (StoreProjectsDtoV2 dto : list) {
                List<StoreProjectStageDto> stageDtoList = stageMap.get(dto.getUid());
                if (CollectionUtils.isNotEmpty(stageDtoList))
                    dto.setStageList(stageDtoList);
            }
        }

        // 按启用字段降序
        return list.stream()
                .sorted(Comparator.comparing(StoreProjectsDtoV2::getEnabled).reversed())
                .collect(Collectors.toList());
    }


}
